package com.ruoyi.web.controller.system.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.web.controller.system.dto.WxPayV3CallbackDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Map;

/**
 * 微信支付V3回调数据解密工具类
 */
public class WxPayV3CallbackUtil {

    private static final Logger log = LoggerFactory.getLogger(WxPayV3CallbackUtil.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 解密微信支付V3回调数据
     *
     * @param callbackData 回调数据
     * @param apiV3Key 商户APIv3密钥
     * @return 解密后的交易数据
     */
    public static Map<String, Object> decryptCallbackData(WxPayV3CallbackDTO callbackData, String apiV3Key) {
        try {
            WxPayV3CallbackDTO.Resource resource = callbackData.getResource();
            if (resource == null) {
                throw new IllegalArgumentException("回调资源数据为空");
            }

            // 验证加密算法
            if (!"AEAD_AES_256_GCM".equals(resource.getAlgorithm())) {
                throw new IllegalArgumentException("不支持的加密算法: " + resource.getAlgorithm());
            }

            // 解密数据
            String decryptedData = decryptAes256Gcm(
                resource.getCiphertext(),
                apiV3Key,
                resource.getAssociatedData(),
                resource.getNonce()
            );

            // 解析解密后的JSON数据
            return objectMapper.readValue(decryptedData, Map.class);

        } catch (Exception e) {
            log.error("解密微信支付V3回调数据失败", e);
            throw new RuntimeException("解密回调数据失败", e);
        }
    }

    /**
     * AEAD_AES_256_GCM 解密算法
     */
    private static String decryptAes256Gcm(String ciphertext, String key, String associatedData, String nonce) {
        try {
            // 将APIv3密钥转换为字节数组
            byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");

            // 创建Cipher实例
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

            // 设置GCMParameterSpec
            GCMParameterSpec parameterSpec = new GCMParameterSpec(128, nonce.getBytes(StandardCharsets.UTF_8));

            // 初始化Cipher为解密模式
            cipher.init(Cipher.DECRYPT_MODE, keySpec, parameterSpec);

            // 如果有附加数据，更新AAD
            if (associatedData != null) {
                cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8));
            }

            // 解密数据
            byte[] ciphertextBytes = Base64Utils.decodeFromString(ciphertext);
            byte[] decryptedBytes = cipher.doFinal(ciphertextBytes);

            return new String(decryptedBytes, StandardCharsets.UTF_8);

        } catch (Exception e) {
            log.error("AEAD_AES_256_GCM解密失败", e);
            throw new RuntimeException("解密失败", e);
        }
    }


    /**
     * 验证回调签名（简化版，实际项目中需要完整实现）
     */
    public static boolean verifySignature(String timestamp, String nonce, String signature, String body) {
        // 在实际项目中，这里需要实现完整的签名验证逻辑
        // 包括获取微信平台证书、验证签名等
        log.info("签名验证: timestamp={}, nonce={}, signature={}", timestamp, nonce, signature);
        return true; // 简化处理，实际项目需要完整验证
    }

    /**
     * 构建成功响应（V3版本返回204状态码）
     */
    public static String buildSuccessResponse() {
        // V3版本成功时返回空响应体，HTTP状态码为200或204
        return "";
    }
}